//
//  AddressBookManager.m
//  TestAB
//
//  Created by Hunk on 12-2-24.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "AddressBookManager.h"

@interface AddressBookManager (Private)

- (NSArray *)personsComparedByName;

- (BOOL)containsGroupName:(NSString *)groupName;

@end

static AddressBookManager *_sharedManager = nil;

@implementation AddressBookManager

- (void)dealloc
{
    SAFE_CFRELEASE(_addressBookRef)
    
    [super dealloc];
}

+ (AddressBookManager *)sharedManager
{
    @synchronized([AddressBookManager class])
    {
        if(!_sharedManager)
		{
			_sharedManager = [[AddressBookManager alloc] init];
		}
		return _sharedManager;
    }
    return nil;
}

- (id)init
{
    if((self = [super init]))
    {
        _addressBookRef = ABAddressBookCreate();
    }
    return self;
}

- (ABAddressBookRef)addressBookRef
{
    return _addressBookRef;
}

- (NSInteger)personCount
{
    return ABAddressBookGetPersonCount(_addressBookRef);
}

#pragma mark -
#pragma mark addressBookPersons
- (NSArray *)addressBookPersons
{   
    NSArray* personArray = [self personsComparedByName];
    
    NSMutableArray* tempPersonArray = [[NSMutableArray alloc] initWithCapacity:[personArray count]];
    
    for(int i = 0; i < [personArray count]; i++)
    {
        ABRecordRef record = [personArray objectAtIndex:i];
        
        AddressBookPerson* addressBookPerson = [[AddressBookPerson alloc] initWithRecord:record];
        
        [tempPersonArray addObject:addressBookPerson];
        
        [addressBookPerson release];
//        SAFE_RELEASE(addressBookPerson)
    }
    
    return [tempPersonArray autorelease];
}

#pragma mark -
#pragma mark addressBookGroups
- (NSArray *)addressBookGroups
{
    CFArrayRef groupsArrayRef = ABAddressBookCopyArrayOfAllGroups(_addressBookRef);
    
    NSMutableArray* abGroupsArray = [[NSMutableArray alloc] initWithCapacity:CFArrayGetCount(groupsArrayRef)];
    
    for(int i = 0; i < CFArrayGetCount(groupsArrayRef); i++)
    {
        ABRecordRef groupRecordRef = (ABRecordRef)CFArrayGetValueAtIndex(groupsArrayRef, i);
        
        AddressBookGroup *addressBookGroup = [[AddressBookGroup alloc] initWithRecord:groupRecordRef];
        
        [abGroupsArray addObject:addressBookGroup];
        SAFE_RELEASE(addressBookGroup)
    }
    
    return [abGroupsArray autorelease];
}

#pragma mark -
#pragma mark Add new group
- (BOOL)addNewGroupWith:(NSString*)newGroupName
{
    if(![self containsGroupName:newGroupName])
    {
        ABRecordRef groupRef = ABGroupCreate();
        
        CFErrorRef error = nil;
        
        ABRecordSetValue(groupRef, kABGroupNameProperty, newGroupName, &error);
        
        if(error)
        {
            CFRelease(groupRef);
            
            return NO;
        }
        
        error = nil;
        
        ABAddressBookAddRecord(_addressBookRef, groupRef, &error);
        
        if(error)
        {
            CFRelease(groupRef);
            
            return NO;
        }
        
        ABAddressBookSave(_addressBookRef, nil);
        
        CFRelease(groupRef);
        
        return YES;
    }
    
    return NO;
}

#pragma mark - 
#pragma mark Remove group
- (BOOL)removeGroup:(AddressBookGroup *)group
{
    if(group)
    {
        CFErrorRef error = nil;
        
        if(ABAddressBookRemoveRecord(_addressBookRef, [group record], &error))
        {
            if(ABAddressBookSave(_addressBookRef, &error))
            {
                return YES;
            }
        }
    }
    return NO;
}

#pragma mark -
#pragma mark add member to group
- (BOOL)addMember:(AddressBookPerson *)person ToGroup:(AddressBookGroup *)group;
{
    for(AddressBookPerson *tempPerson in [group groupMembers])
    {
        if([tempPerson recordID] == [person recordID])
        {
            return NO;
        }
    }
    
    CFErrorRef error = nil;
    
    if(ABAddressBookAddRecord(_addressBookRef, [person record], &error))
    {
        if(ABGroupAddMember([group record], [person record], &error))
        {
            if(ABAddressBookSave(_addressBookRef, &error))
            {
                return YES;
            }
        }
    }
    
    return NO;
}

#pragma mark -
#pragma mark remove member from group
- (BOOL)removeMember:(AddressBookPerson *)person fromGroup:(AddressBookGroup *)group
{   
    CFErrorRef error = nil;
    
    if(ABGroupRemoveMember([group record], [person record], &error))
    {
        if(ABAddressBookSave(_addressBookRef, &error))
        {
            return YES;
        }
    }
    return NO;
}

#pragma mark -
#pragma mark Private methods
#pragma mark -
#pragma mark containsGroupName
- (BOOL)containsGroupName:(NSString *)groupName
{
    if(!groupName)
    {
        return NO;
    }
    
    NSArray *allGroups = [self addressBookGroups];
    
    for(AddressBookGroup *addressBookGroup in allGroups)
    {
        if([[addressBookGroup groupName] isEqualToString:groupName])
        {
            return YES;
        }
    }
    return NO;
}

#pragma mark -
#pragma mark personsComparedByName
- (NSArray *)personsComparedByName
{       
//    CFArrayRef allPeopleArray = ABAddressBookCopyArrayOfAllPeople(_addressBookRef);
    
    CFArrayRef allPeopleArray = ABAddressBookCopyArrayOfAllPeople(ABAddressBookCreate());
    
    CFMutableArrayRef tempArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, 
                                                           CFArrayGetCount(allPeopleArray), 
                                                           allPeopleArray);
    CFRelease(allPeopleArray);
    
    CFArraySortValues(tempArray, 
                      CFRangeMake(0, CFArrayGetCount(tempArray)), 
                      (CFComparatorFunction)ABPersonComparePeopleByName,
                      (void*)ABPersonGetSortOrdering());
    
    NSArray* array = [NSArray arrayWithArray:(NSMutableArray*)tempArray];
    
    CFRelease(tempArray);
    
    return array;
}

@end
